package cn.snsprj.authserver.controller;

import cn.snsprj.authserver.common.ConstCode.ConstCodeCookie;
import cn.snsprj.authserver.common.ConstCode.ConstCodeUrl;
import cn.snsprj.authserver.common.ErrorCode.ErrorCodeUser;
import cn.snsprj.authserver.common.Router.RouterLogin;
import cn.snsprj.authserver.common.ServerResponse;
import cn.snsprj.authserver.util.CookieUtil;
import cn.snsprj.authserver.util.HttpUtil;
import cn.snsprj.authserver.util.RedisUtil;
import cn.snsprj.authserver.util.URLUtil;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * @author SKH
 * @date 2018-08-20 09:50
 **/
@Controller
public class IndexController {

    private Logger logger = LoggerFactory.getLogger(IndexController.class);

    @Autowired
    RedisUtil redisUtil;

    /**
     * 验证TGT
     */
    @RequestMapping(value = "/auth", method = {RequestMethod.GET})
    public String authTGT(HttpServletRequest request,
            @RequestParam(ConstCodeUrl.URL_KEY_SOURCE_URL) String sourceUrl) {

        Cookie[] cookies = request.getCookies();

        if (cookies == null || cookies.length == 0) {

            HttpSession session = request.getSession(true);

            // 把sourceUrl存储到session
            session.setAttribute(ConstCodeUrl.URL_KEY_SOURCE_URL, sourceUrl);

            // 返回到登录页面
            return URLUtil.redirect(RouterLogin.LOGIN_VIEW);
        } else {
            String cookieServiceTicket = CookieUtil
                    .getCookie(request, ConstCodeCookie.COOKIE_SERVICE_TICKET);

            if (StringUtils.isNotBlank(cookieServiceTicket)){

                // 验证ticket
                logger.info("====>serviceTicket is {}", cookieServiceTicket);
                String redisServiceTicket = (String) redisUtil.get(cookieServiceTicket);

                if (!StringUtils.equals(cookieServiceTicket, redisServiceTicket)) {

                    // 验证未通过，返回到登录页面
                    return URLUtil.redirect(RouterLogin.LOGIN_VIEW);

                } else {

                    // 验证通过，返回ST，重定向到浏览器
                    return URLUtil.redirectWithST(sourceUrl, cookieServiceTicket);
                }
            }else {

                // 验证未通过，返回到登录页面
                return URLUtil.redirect(RouterLogin.LOGIN_VIEW);
            }
        }
    }


    /**
     * 验证service_ticket有效性
     *
     * @param serviceTicket
     * @return
     */
    @RequestMapping(value = "/verify_st", method = {RequestMethod.GET})
    @ResponseBody
    public ServerResponse authServiceTicket(@RequestParam("service_ticket") String serviceTicket){

        String redisServiceTicket = (String) redisUtil.get(serviceTicket);

        if (!StringUtils.equals(serviceTicket, redisServiceTicket)) {

            // 验证未通过
            return ServerResponse.createByError(ErrorCodeUser.SERVICE_TICKET_INVALID);

        } else {

            // 验证通过
            return ServerResponse.createBySuccess();
        }
    }

    /**
     * 处理认证中心发起的登录请求
     *
     * @param account account
     * @param password password
     */
    @RequestMapping(value = "/login", method = {RequestMethod.POST})
    @ResponseBody
    public ServerResponse login(HttpServletRequest request,
            HttpServletResponse response,
            @RequestParam("account") String account,
            @RequestParam("password") String password) {

        HttpSession session = request.getSession(false);
        String sourceUrl = null;
        if (session != null){
            sourceUrl = String.valueOf(session.getAttribute(ConstCodeUrl.URL_KEY_SOURCE_URL));
        }

        if (StringUtils.isBlank(sourceUrl)){
            // TODO 默认跳转地址
            sourceUrl = "http://clienta.com:8081/user/info";
        }

        if (StringUtils.isBlank(account) || StringUtils.isBlank(password)) {
            return ServerResponse.createByError(ErrorCodeUser.USER_USERNAME_PASSWORD_MISMATCH,
                    "用户名密码错误");
        } else {

            // TODO 验证用户名密码
            if (!StringUtils.equals(account, "root") || !StringUtils.equals(password, "root")) {
                return ServerResponse.createByError(ErrorCodeUser.USER_USERNAME_PASSWORD_MISMATCH,
                        "用户名密码错误");
            }
        }

        // TODO 生成serviceTicket
        String serviceTicket = this.getRandomString(16);

        redisUtil.setEx(serviceTicket, serviceTicket, 3600);

        CookieUtil.writeCookie(response, ConstCodeCookie.COOKIE_SERVICE_TICKET, serviceTicket);

//        redirectAttributes.addFlashAttribute(ConstCodeCookie.COOKIE_SERVICE_TICKET, serviceTicket);

        String targetUrl = URLUtil.getURLWithST(sourceUrl, serviceTicket);
        return ServerResponse.createBySuccess("", targetUrl);
    }

    /**
     * 返回认证中心登录页面
     */
    @RequestMapping(value = RouterLogin.LOGIN_VIEW, method = {RequestMethod.GET})
    public String loginView() {

        return "login";
    }

    /**
     * 清除cookie，页面跳转由client端完成
     */
    @RequestMapping(value = "/logout", method = {RequestMethod.GET})
    public String logout(HttpServletRequest request, HttpServletResponse response) {

        String sourceUrl = request.getParameter(ConstCodeUrl.URL_KEY_SOURCE_URL);
        logger.info("====>sourceUrl is {}", sourceUrl);

        // TODO 清除service_ticket
        String cookieServiceTicket = CookieUtil
                .getCookie(request, ConstCodeCookie.COOKIE_SERVICE_TICKET);
        if (StringUtils.isNotBlank(cookieServiceTicket)){
            redisUtil.delete(cookieServiceTicket);
        }

        //  清除session
        HttpSession session = request.getSession();
        if (session != null) {
            session.invalidate();
        }

        // 清除cookie
        CookieUtil.deleteCookie(request, response, ConstCodeCookie.COOKIE_SERVICE_TICKET);

        // TODO 通知所有client退出登录
        Map<String, Object> parmMap = new HashMap<>();
        parmMap.put("serviceTicket",cookieServiceTicket);

        String clientALogoutUrl = "http://clienta.com:8081/notified_logout";
        HttpUtil.doGet(clientALogoutUrl,parmMap);

        String clientBLogoutUrl = "http://clientb.com:8081/notified_logout";
        HttpUtil.doGet(clientBLogoutUrl,parmMap);

        return URLUtil.redirect(sourceUrl);
    }

    /*
     * 获取随机的字符
     */
    private String getRandomString(int length) {

        // 随机产生只有数字的字符串
//        String seedString = "0123456789";

        // 随机产生只有字母的字符串
        // String seedString = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

        // 随机产生数字与字母组合的字符串
        String seedString = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

        StringBuilder rendString = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < length; i++) {
            int num = random.nextInt(seedString.length());
            rendString.append(String.valueOf(seedString.charAt(num)));
        }
        return rendString.toString();
    }
}
